namespace
是在 PHP 5.3 中加入的,如果你学过C#和Java,那命名空间就不算什么新事物。 不过在 PHP 当中还是有着相当重要的意义。
如前所述,PHP 社区已经有许多开发者开发了大量的代码。这意味着一个类库的 PHP 代码可能使用了另外一个类库中相同的类名。如果他们使用同一个命名空间,那将会产生冲突导致异常。
命名空间
解决了这个问题。如 PHP 手册里所描述,命名空间好比操作系统中的目录,两个同名的文件可以共存在不同的目录下。同理两个同名的 PHP 类可以在不同的 PHP 命名空间下共存,就这么简单。
因此把你的代码放在你的命名空间下就非常重要,避免其他开发者担心与第三方类库冲突。
PSR-4 提供了一种命名空间的推荐使用方式,它提供一个标准的文件、类和命名空间的使用惯例,进而让代码做到随插即用。
2014 年 10 月,PHP-FIG 废弃了上一个自动加载标准: PSR-0,而采用新的自动加载标准 PSR-4。但 PSR-4 要求 PHP 5.3 以上的版本,而许多项目都还是使用 PHP 5.2,所以目前两者都能使用。
如果你在新应用或扩展包中使用自动加载标准,应优先考虑使用 PSR-4。
通过关键字namespace
声明。可以在同一个文件中定义不同的命名空间代码,全局的非命名空间代码与命名空间中的代码通过大括号的形式可以组合在一起
<?php # 命名空间TestA namespace TestA{ class TestA{} function test(){} } # 命名空间TestB namespace TestB{ class TestB{} function test(){} } # 全局的非命名空间 namespace{ class TestC{} function test(){} }
与目录和文件的关系很像,PHP
命名空间也允许指定层次的命名空间的名称
<?php namespace a\b\Test; ?>
通过关键字use
引入,通过as
定义别名
引入命名空间三种情况:
a
下,使用 $a = new foo()
,代表引用的是 a\foo
。在命名空间为全局的情况下,使用该方法则引用的是 foo
。a
下,使用 $a = new b\foo()
;代码引入的是 a\b\foo
。
在命名为全局的情况下,使用该方法引入的是 b\foo
。a
下,$a = new \c\b\foo()
;这种情况下,总是引入为 c\b\foor
文件file1.php 文件代码
<?php namespace Foo\Bar\subnamespace; const FOO = 1; function foo() {} class foo { static function staticmethod() {} } ?>
file2.php 文件代码
<?php namespace Foo\Bar; include 'file1.php'; const FOO = 2; function foo() {} class foo { static function staticmethod() {} } /* 非限定名称 */ foo(); // 解析为 Foo\Bar\foo resolves to function Foo\Bar\foo foo::staticmethod(); // 解析为类 Foo\Bar\foo的静态方法staticmethod。 //resolves to class Foo\Bar\foo, method staticmethod echo FOO; // resolves to constant Foo\Bar\FOO /* 限定名称 */ subnamespace\foo(); // 解析为函数 Foo\Bar\subnamespace\foo subnamespace\foo::staticmethod(); // 解析为类 Foo\Bar\subnamespace\foo, // 以及类的方法 staticmethod echo subnamespace\FOO; // 解析为常量 Foo\Bar\subnamespace\FOO /* 完全限定名称 */ \Foo\Bar\foo(); // 解析为函数 Foo\Bar\foo \Foo\Bar\foo::staticmethod(); // 解析为类 Foo\Bar\foo, 以及类的方法 staticmethod echo \Foo\Bar\FOO; // 解析为常量 Foo\Bar\FOO ?>
上述三种方式其实就是文件路径中绝对路径和相对路径。
注意:访问任意全局类、函数或变量,都可以使用完全限定名称,例如 \strlen()
或者 \Exception
。
<?php namespace foo; use \A\B\TestA; #导入命名空间 use \A\B\TestB as TB; #导入命名空间,并别名为TB ?>
namespace
和__NAMESPACE__
魔术常量
namespace
用于定义命名空间,__NAMESPACE__
是包含当前命名空间的字符串,在全局的情况下,它是一个空字符串''
。
NAMESPACE 示例, 在命名空间中的代码
<?php namespace MyProject; echo '"', __NAMESPACE__, '"'; // 输出 "MyProject" ?>
NAMESPACE 示例,全局代码
<?php echo '"', __NAMESPACE__, '"'; // 输出 "" ?>
常量 NAMESPACE 在动态创建名称时很有用,例如:使用 __NAMESPACE__
动态创建名称
<?php namespace MyProject; function get($classname) { $a = __NAMESPACE__ . '\\' . $classname; return new $a; } ?>
1.只有三种类型受命名空间的影响:类、函数、常量
2.使用namespace来声明(类似文件目录)
3.除非使用declare,否则namespace前不能有任何PHP和HTML代码(包括空白符)
4.同一命名空间可以定义在多个文件中,但分割开的命名空间中,上述三个类型也不能重名
在声明命名空间之前唯一合法的代码是用于定义源文件编码方式的 declare 语句。所有非 PHP 代码包括空白符都不能出现在命名空间的声明之前。
<?php declare(encoding='UTF-8'); //定义多个命名空间和不包含在命名空间中的代码 namespace MyProject { const CONNECT_OK = 1; class Connection { /* ... */ } function connect() { /* ... */ } } namespace { // 全局代码 session_start(); $a = MyProject\connect(); echo MyProject\Connection::start(); } ?>
以下代码会出现语法错误:
<html> <?php namespace MyProject; // 命名空间前出现了“” 会致命错误 - 命名空间必须是程序脚本的第一条语句 ?>